<?php

// +----------------------------------------------------------------------
// | Copyright (c) 2020 All rights reserved.
// +----------------------------------------------------------------------
// | User: Simony <1362229026@qq.com>
// | wechat: Shen86579595
// +----------------------------------------------------------------------

namespace app\common\logic\file;

use app\common\logic\OssLogic;

class FileLogic
{
    private $_dir = DS;
    private $_file_size = 10;

    public function __construct()
    {
        $this->init();
    }

    /**
     * User:Simony
     * Function: 初始化配置
     */
    private function init()
    {
        $this->_file_size = sysConfig('file_size') ?: 10;
    }

    public function setDir($dir)
    {
        $this->_dir = $dir . DS;
        $this->createDir($this->_dir);
    }

    /**
     * User:Simony
     * Function: 上传图片
     * @return mixed
     */
    public function uploadImg($dir = null, $watermark = true)
    {
        $file_store = sysConfig('file_store') ?? 'local'; //oss
        $file_store = ucfirst($file_store);
        if (!is_null($dir)) $this->setDir($dir);
        if ($_FILES['image']) {
            try {
                $file = request()->file('image');
                $fileArr = [];
                if (!is_array($file)) {
                    $fileArr[] = $file;
                } else {
                    $fileArr = $file;
                }
                $res = [];

                foreach ($fileArr as $fv) {
                    //验证
                    $validate = new \think\Validate([
                            'file' => 'image|fileSize:40000000|fileExt:jpg,jpeg,gif,png']
                    );
                    $data = [
                        'file' => $fv,
                    ];

                    if (!$validate->check($data)) {
                        throw new \Exception($validate->getError());
                    }

                    //local
                    $maxSize = $this->_file_size * 1024 * 1024;
                    if (!$fv->checkSize($maxSize)) {
                        //压缩
                        $fileArr = $this->compressImage($fv);
                    } else {
                        //上传
                        $fileArr = $this->uploadImage($fv);

                    }

                    list($realPath, $info, $imageType) = $fileArr;
                    if ($watermark) {
                        $image = \think\Image::open(ROOT_PATH . DS . 'public' . DS . $realPath);
                        // 给原图左上角添加水印并保存water_image.png
                        $image->water(ROOT_PATH . DS . 'public' . config('app.fixed_image_path.water_image'), \think\Image::WATER_SOUTHEAST)->save(ROOT_PATH . DS . 'public' . DS . $realPath);
                    }

                    $res = [
                        'absoluteUrl' => DS . $realPath,
                        'relativeUrl' => ROOT_PATH . DS . 'public' . DS . $realPath,
                    ];


                    if ($file_store == 'Local') {
                        unset($info);//解除图片的进程占用
                        return ds_arr(200, '上传成功', ['absoluteUrl' => $res['absoluteUrl']]);
                    } else {
                        //上传到oss
                        if ($info) {
                            //oss or local
                            list($result, $savePath) = $this->uploadOss($realPath, $imageType);
                            $res[] = [
                                'absoluteUrl' => $result,
                                'relativeUrl' => OssLogic::$prefix . $savePath
                            ];
                        } else {
                            return ds_arr(200, $fv->getError(), null);//上传错误提示错误信息
                        }
                    }
                }
                return ds_arr(200, '上传成功', $this->dataFormat($file, $res));
            } catch (\Exception $e) {
                return ds_arr(400, $e->getMessage(), null);
                return ds_arr(400, '上传出错', null);
            }
        }
    }

    /**
     * User:Simony
     * Function: base64图片上传
     * @return mixed
     */
    public function base64Image($dir = null, $watermark = true)
    {

        $file_store = sysConfig('file_store') ?? 'local'; //oss
        $file_store = ucfirst($file_store);

        if (!is_null($dir)) $this->setDir($dir);
        $imagesArr = input('image/a');
        if (empty($imagesArr)) {
            return ds_arr(400, '请选择图片上传', null);
        }

        try {
            $res = [];
            foreach ($imagesArr as $fv) {
                if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $fv, $result)) {
                    $type = $result[2]; //图片后缀
                    $dir = $this->_dir . date('Ymd') . DS;
                    $this->createDir($dir);
                    $filePath = $dir . md5(time() . mt_rand(1, 999999999)) . ".{$type}"; //文件路径

                    //local
                    $localUpload = file_put_contents($filePath, base64_decode(str_replace($result[1], '', $fv)));
                    if ($localUpload) {

                        if ($watermark) {
                            $image = \think\Image::open(ROOT_PATH . DS . 'public' . DS . $filePath);
                            // 给原图左上角添加水印并保存water_image.png
                            $image->water(ROOT_PATH . DS . 'public' . config('app.fixed_image_path.water_image'), \think\Image::WATER_SOUTHEAST)->save(ROOT_PATH . DS . 'public' . DS . $filePath);
                        }

                        if ($file_store == 'Local') {
                            $res[] = [
                                'absoluteUrl' => DS . $filePath,
                                'relativeUrl' => ROOT_PATH . DS . 'public' . DS . $filePath,
                            ];
                        } elseif ($file_store == 'Oss') {
                            list($result, $savePath) = $this->uploadOss($filePath, '.' . $type);
                            $res[] = [
                                'absoluteUrl' => $result,
                                'relativeUrl' => OssLogic::$prefix . $savePath
                            ];
                        }
                    } else {
                        throw new \Exception('上传失败100');
                    }
                    return ds_arr(200, '上传成功', $this->dataFormat($imagesArr, $res));

                } else {
                    throw new \Exception('上传失败200，格式不正确');
                }
            }
            return ds_arr(200, '上传成功', $this->dataFormat($_POST['image'], $res));
        } catch (\Exception $e) {
            return ds_arr(400, $e->getMessage(), null);
        }
    }

    /**
     * User:Simony
     * Function:个书画数据
     * @param $file 文件变量
     * @param $data 要处理的数据
     * @return array
     */
    protected function dataFormat($file, $data)
    {
        if (is_array($file) && count($file) > 1) {
            $list = [
                'list' => $data
            ];
        } else {
            $list = $data[0];
        }
        return $list;
    }

    /**
     * User:Simony
     * Function: 创建文件夹
     */
    private function createDir($dir)
    {
        if (!is_dir($dir)) {
            //检查是否有该文件夹，如果没有就创建，并给予最高权限
            mkdir($dir, 0777, true);
        }
    }

    /**
     * User:Simony
     * Function: oss路径
     * @param $type
     * @return string
     */
    private function getOssPath($type)
    {
        return $type . '/' . date('Y') . '/' . date('m-d') . '/' . md5(time() . mt_rand(1, 999999999));
    }

    /**
     * User:Simony
     * Function:压缩图片
     * @param $file 上传突破对象
     * @return array
     */
    private function compressImage($file)
    {
        $image = \think\Image::open($file);
        $imageType = $image->type() == "jpeg" ? 'jpg' : $image->type();
        $fileName = md5(time() . mt_rand(1, 999999999)) . '.' . $imageType;
        $dir = $this->_dir;
        $filePath = $dir . $fileName;
        $info = $image->thumb(800, 800, 1)->save($filePath, NULL, 100);
        return [$filePath, $info, '.' . $imageType];
    }

    /**
     * User:Simony
     * Function:上传图片
     * @param $file
     * @return array
     */
    private function uploadImage($file)
    {
        $dir = $this->_dir;
        $info = $file->move($dir, true);
        return [$dir . str_replace('\\', '/', $info->getSaveName()), $info, $info->getInfo('name')];
    }

    /**
     * User:Simony
     * Function:上传到oss
     * @param $realPath 文件绝对路径
     * @param $imageType 文件后缀
     * @return array
     * @throws \Exception
     */
    public function uploadOss($realPath, $imageType = 'jpg')
    {
        $ossLogic = OssLogic::getInstance();
//        $path = $this->getOssPath('app') . $upimageType;
//        $path= $realPath;
////        echo $imageType;die;
//        $result = $ossLogic->uploadFile($realPath, $path);

        $result = $ossLogic->uploadFile($realPath);
        if ($result === false) {
            throw new \Exception($ossLogic->getError());
        }
        $info = null;//关闭文件句柄，不然无法删除
        @unlink($realPath); //上传后删除
        $savePath = (str_replace($ossLogic->getSiteUrl(), '', $result));
        return [$result, $savePath];
    }

    /**
     * User:Simony
     * Function:上传到本地
     * @param $realPath 文件绝对路径
     * @param $imageType 文件后缀
     * @return array
     * @throws \Exception
     */

    public function uploadLocal($realPath)
    {
        return ['', $realPath];
    }

    /**
     * User: Simony
     * Function:删除文件
     * @param $filePath
     */
    public function deleteFile($filePath)
    {
        $url_info = parse_url($filePath);
        $file_path = $url_info['path'];
        if ($this->isHttpOrHttps($filePath)) {

            OssLogic::getInstance()->deleteFile($file_path);
        } else {
            $filePath = ROOT_PATH . 'public' . $filePath;
            if (is_file($filePath)) @unlink($filePath);
        }
    }

    /**
     * User: Simony
     * Function:文件是否存在
     * @param $filePath
     * @return bool
     */
    public function fileExists($filePath)
    {

        if ($this->isHttpOrHttps($filePath)) {
            $resource = @file_get_contents($filePath, false, $context = stream_context_create(['http' => ['timeout' => 3]]));
            return $resource ? true : false;
        } else {
            $url_info = parse_url($filePath);
            $filePath = ROOT_PATH . 'public' . $url_info['path'];
            return file_exists($filePath);
        }

    }

    /**
     * User: Simony
     * Function:拷贝文件
     * @param $old_path
     * @param $new_path
     * @throws \Exception
     */
    public function copyFile($old_path, $new_path)
    {
        if ($this->isHttpOrHttps($old_path)) {
            $new_url_info = parse_url($new_path);
            file_put_contents(ROOT_PATH . 'public' . $new_url_info['path'], file_get_contents($old_path));

            $res = $this->uploadOss(substr($new_url_info['path'], 1));
        } else {
            copy(ROOT_PATH . 'public' . $old_path, ROOT_PATH . 'public' . $new_path);
        }
    }

    public function getRealPath($path){
        if ($this->isHttpOrHttps($path)) {
            return $path;
        } else {
            return SITE_URL. $path;
        }
    }


    public function getLocalPath($path){
        if ($this->isHttpOrHttps($path)) {
            return $path;
        } else {
            return ROOT_PATH.'public'. $path;
        }
    }


    public function getFileInfo($filePath){
        $path_info = pathinfo($filePath);

        if($this->isHttpOrHttps($filePath)){
            $real_dir_path = $relative_dir_path =  $path_info['dirname'];
            $real_file_path = $relative_file_path = $filePath;
        }else{
             $real_dir_path = ROOT_PATH . 'public' . $path_info['dirname'];
             $relative_dir_path =  $path_info['dirname'];
             $real_file_path=$real_dir_path.'/'.$path_info['basename'];
             $relative_file_path=$relative_dir_path.'/'.$path_info['basename'];;
        }

        return [
                'real_dir_path'=> $real_dir_path,
                'relative_dir_path'=>  $relative_dir_path,
                'real_file_path'=> $real_file_path,
                'relative_file_path'=> $relative_file_path,
                'basename'=>$path_info['basename'],
                'filename'=>$path_info['filename'],
                'extension'=>$path_info['extension'],
        ];
    }



    public function isHttpOrHttps($url){
        $preg = "/^http(s)?:\\/\\/.+/";
        return preg_match($preg,$url)?true:false;
    }

}
